package roaring
import (
"fmt"
"unsafe"
)
type bitmapContainer struct {
cardinality int
bitmap []uint64
}
func (bc bitmapContainer ) String () string {
var s string
for it := bc .getShortIterator (); it .hasNext (); {
s += fmt .Sprintf ("%v, " , it .next ())
}
return s
}
func newBitmapContainer() *bitmapContainer {
p := new (bitmapContainer )
size := (1 << 16 ) / 64
p .bitmap = make ([]uint64 , size , size )
return p
}
func newBitmapContainerwithRange(firstOfRun , lastOfRun int ) *bitmapContainer {
bc := newBitmapContainer ()
bc .cardinality = lastOfRun - firstOfRun + 1
if bc .cardinality == maxCapacity {
fill (bc .bitmap , uint64 (0xffffffffffffffff ))
} else {
firstWord := firstOfRun / 64
lastWord := lastOfRun / 64
zeroPrefixLength := uint64 (firstOfRun & 63 )
zeroSuffixLength := uint64 (63 - (lastOfRun & 63 ))
fillRange (bc .bitmap , firstWord , lastWord +1 , uint64 (0xffffffffffffffff ))
bc .bitmap [firstWord ] ^= ((uint64 (1 ) << zeroPrefixLength ) - 1 )
blockOfOnes := (uint64 (1 ) << zeroSuffixLength ) - 1
maskOnLeft := blockOfOnes << (uint64 (64 ) - zeroSuffixLength )
bc .bitmap [lastWord ] ^= maskOnLeft
}
return bc
}
func (bc *bitmapContainer ) minimum () uint16 {
for i := 0 ; i < len (bc .bitmap ); i ++ {
w := bc .bitmap [i ]
if w != 0 {
r := countTrailingZeros (w )
return uint16 (r + i *64 )
}
}
return MaxUint16
}
func clz(i uint64 ) int {
n := 1
x := uint32 (i >> 32 )
if x == 0 {
n += 32
x = uint32 (i )
}
if x >>16 == 0 {
n += 16
x = x << 16
}
if x >>24 == 0 {
n += 8
x = x << 8
}
if x >>28 == 0 {
n += 4
x = x << 4
}
if x >>30 == 0 {
n += 2
x = x << 2
}
return n - int (x >>31 )
}
func (bc *bitmapContainer ) maximum () uint16 {
for i := len (bc .bitmap ); i > 0 ; i -- {
w := bc .bitmap [i -1 ]
if w != 0 {
r := clz (w )
return uint16 ((i -1 )*64 + 63 - r )
}
}
return uint16 (0 )
}
func (bc *bitmapContainer ) iterate (cb func (x uint16 ) bool ) bool {
iterator := bitmapContainerShortIterator {bc , bc .NextSetBit (0 )}
for iterator .hasNext () {
if !cb (iterator .next ()) {
return false
}
}
return true
}
type bitmapContainerShortIterator struct {
ptr *bitmapContainer
i int
}
func (bcsi *bitmapContainerShortIterator ) next () uint16 {
j := bcsi .i
bcsi .i = bcsi .ptr .NextSetBit (uint (bcsi .i ) + 1 )
return uint16 (j )
}
func (bcsi *bitmapContainerShortIterator ) hasNext () bool {
return bcsi .i >= 0
}
func (bcsi *bitmapContainerShortIterator ) peekNext () uint16 {
return uint16 (bcsi .i )
}
func (bcsi *bitmapContainerShortIterator ) advanceIfNeeded (minval uint16 ) {
if bcsi .hasNext () && bcsi .peekNext () < minval {
bcsi .i = bcsi .ptr .NextSetBit (uint (minval ))
}
}
func newBitmapContainerShortIterator(a *bitmapContainer ) *bitmapContainerShortIterator {
return &bitmapContainerShortIterator {a , a .NextSetBit (0 )}
}
func (bc *bitmapContainer ) getShortIterator () shortPeekable {
return newBitmapContainerShortIterator (bc )
}
type reverseBitmapContainerShortIterator struct {
ptr *bitmapContainer
i int
}
func (bcsi *reverseBitmapContainerShortIterator ) next () uint16 {
if bcsi .i == -1 {
panic ("reverseBitmapContainerShortIterator.next() going beyond what is available" )
}
j := bcsi .i
bcsi .i = bcsi .ptr .PrevSetBit (bcsi .i - 1 )
return uint16 (j )
}
func (bcsi *reverseBitmapContainerShortIterator ) hasNext () bool {
return bcsi .i >= 0
}
func newReverseBitmapContainerShortIterator(a *bitmapContainer ) *reverseBitmapContainerShortIterator {
if a .cardinality == 0 {
return &reverseBitmapContainerShortIterator {a , -1 }
}
return &reverseBitmapContainerShortIterator {a , int (a .maximum ())}
}
func (bc *bitmapContainer ) getReverseIterator () shortIterable {
return newReverseBitmapContainerShortIterator (bc )
}
type bitmapContainerManyIterator struct {
ptr *bitmapContainer
base int
bitset uint64
}
func (bcmi *bitmapContainerManyIterator ) nextMany (hs uint32 , buf []uint32 ) int {
n := 0
base := bcmi .base
bitset := bcmi .bitset
for n < len (buf ) {
if bitset == 0 {
base ++
if base >= len (bcmi .ptr .bitmap ) {
bcmi .base = base
bcmi .bitset = bitset
return n
}
bitset = bcmi .ptr .bitmap [base ]
continue
}
t := bitset & -bitset
buf [n ] = uint32 (((base * 64 ) + int (popcount (t -1 )))) | hs
n = n + 1
bitset ^= t
}
bcmi .base = base
bcmi .bitset = bitset
return n
}
func (bcmi *bitmapContainerManyIterator ) nextMany64 (hs uint64 , buf []uint64 ) int {
n := 0
base := bcmi .base
bitset := bcmi .bitset
for n < len (buf ) {
if bitset == 0 {
base ++
if base >= len (bcmi .ptr .bitmap ) {
bcmi .base = base
bcmi .bitset = bitset
return n
}
bitset = bcmi .ptr .bitmap [base ]
continue
}
t := bitset & -bitset
buf [n ] = uint64 (((base * 64 ) + int (popcount (t -1 )))) | hs
n = n + 1
bitset ^= t
}
bcmi .base = base
bcmi .bitset = bitset
return n
}
func newBitmapContainerManyIterator(a *bitmapContainer ) *bitmapContainerManyIterator {
return &bitmapContainerManyIterator {a , -1 , 0 }
}
func (bc *bitmapContainer ) getManyIterator () manyIterable {
return newBitmapContainerManyIterator (bc )
}
func (bc *bitmapContainer ) getSizeInBytes () int {
return len (bc .bitmap ) * 8
}
func (bc *bitmapContainer ) serializedSizeInBytes () int {
return len (bc .bitmap ) * 8
}
const bcBaseBytes = int (unsafe .Sizeof (bitmapContainer {}))
func bitmapContainerSizeInBytes() int {
return bcBaseBytes + (1 <<16 )/8
}
func bitmapEquals(a , b []uint64 ) bool {
if len (a ) != len (b ) {
return false
}
for i , v := range a {
if v != b [i ] {
return false
}
}
return true
}
func (bc *bitmapContainer ) fillLeastSignificant16bits (x []uint32 , i int , mask uint32 ) int {
pos := i
base := mask
for k := 0 ; k < len (bc .bitmap ); k ++ {
bitset := bc .bitmap [k ]
for bitset != 0 {
t := bitset & -bitset
x [pos ] = base + uint32 (popcount (t -1 ))
pos ++
bitset ^= t
}
base += 64
}
return pos
}
func (bc *bitmapContainer ) equals (o container ) bool {
srb , ok := o .(*bitmapContainer )
if ok {
if srb .cardinality != bc .cardinality {
return false
}
return bitmapEquals (bc .bitmap , srb .bitmap )
}
if bc .getCardinality () != o .getCardinality () {
return false
}
ait := o .getShortIterator ()
bit := bc .getShortIterator ()
for ait .hasNext () {
if bit .next () != ait .next () {
return false
}
}
return true
}
func (bc *bitmapContainer ) iaddReturnMinimized (i uint16 ) container {
bc .iadd (i )
if bc .isFull () {
return newRunContainer16Range (0 , MaxUint16 )
}
return bc
}
func (bc *bitmapContainer ) iadd (i uint16 ) bool {
x := int (i )
previous := bc .bitmap [x /64 ]
mask := uint64 (1 ) << (uint (x ) % 64 )
newb := previous | mask
bc .bitmap [x /64 ] = newb
bc .cardinality += int ((previous ^ newb ) >> (uint (x ) % 64 ))
return newb != previous
}
func (bc *bitmapContainer ) iremoveReturnMinimized (i uint16 ) container {
if bc .iremove (i ) {
if bc .cardinality == arrayDefaultMaxSize {
return bc .toArrayContainer ()
}
}
return bc
}
func (bc *bitmapContainer ) iremove (i uint16 ) bool {
if bc .contains (i ) {
bc .cardinality --
bc .bitmap [i /64 ] &^= (uint64 (1 ) << (i % 64 ))
return true
}
return false
}
func (bc *bitmapContainer ) isFull () bool {
return bc .cardinality == int (MaxUint16 )+1
}
func (bc *bitmapContainer ) getCardinality () int {
return bc .cardinality
}
func (bc *bitmapContainer ) isEmpty () bool {
return bc .cardinality == 0
}
func (bc *bitmapContainer ) clone () container {
ptr := bitmapContainer {bc .cardinality , make ([]uint64 , len (bc .bitmap ))}
copy (ptr .bitmap , bc .bitmap [:])
return &ptr
}
func (bc *bitmapContainer ) iaddRange (firstOfRange , lastOfRange int ) container {
bc .cardinality += setBitmapRangeAndCardinalityChange (bc .bitmap , firstOfRange , lastOfRange )
return bc
}
func (bc *bitmapContainer ) iremoveRange (firstOfRange , lastOfRange int ) container {
bc .cardinality += resetBitmapRangeAndCardinalityChange (bc .bitmap , firstOfRange , lastOfRange )
if bc .getCardinality () <= arrayDefaultMaxSize {
return bc .toArrayContainer ()
}
return bc
}
func (bc *bitmapContainer ) inot (firstOfRange , endx int ) container {
if endx -firstOfRange == maxCapacity {
flipBitmapRange (bc .bitmap , firstOfRange , endx )
bc .cardinality = maxCapacity - bc .cardinality
} else if endx -firstOfRange > maxCapacity /2 {
flipBitmapRange (bc .bitmap , firstOfRange , endx )
bc .computeCardinality ()
} else {
bc .cardinality += flipBitmapRangeAndCardinalityChange (bc .bitmap , firstOfRange , endx )
}
if bc .getCardinality () <= arrayDefaultMaxSize {
return bc .toArrayContainer ()
}
return bc
}
func (bc *bitmapContainer ) not (firstOfRange , endx int ) container {
answer := bc .clone ()
return answer .inot (firstOfRange , endx )
}
func (bc *bitmapContainer ) or (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .orArray (x )
case *bitmapContainer :
return bc .orBitmap (x )
case *runContainer16 :
if x .isFull () {
return x .clone ()
}
return x .orBitmapContainer (bc )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) orCardinality (a container ) int {
switch x := a .(type ) {
case *arrayContainer :
return bc .orArrayCardinality (x )
case *bitmapContainer :
return bc .orBitmapCardinality (x )
case *runContainer16 :
return x .orBitmapContainerCardinality (bc )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) ior (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .iorArray (x )
case *bitmapContainer :
return bc .iorBitmap (x )
case *runContainer16 :
if x .isFull () {
return x .clone ()
}
for i := range x .iv {
bc .iaddRange (int (x .iv [i ].start ), int (x .iv [i ].last ())+1 )
}
if bc .isFull () {
return newRunContainer16Range (0 , MaxUint16 )
}
return bc
}
panic (fmt .Errorf ("unsupported container type %T" , a ))
}
func (bc *bitmapContainer ) lazyIOR (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .lazyIORArray (x )
case *bitmapContainer :
return bc .lazyIORBitmap (x )
case *runContainer16 :
if x .isFull () {
return x .clone ()
}
bitmap := bc .bitmap
for _ , iv := range x .iv {
start := int (iv .start )
end := int (iv .last ()) + 1
if start >= end {
continue
}
firstword := start / 64
endword := (end - 1 ) / 64
if firstword == endword {
bitmap [firstword ] |= (^uint64 (0 ) << uint (start %64 )) & (^uint64 (0 ) >> (uint (-end ) % 64 ))
continue
}
bitmap [firstword ] |= ^uint64 (0 ) << uint (start %64 )
for i := firstword + 1 ; i < endword ; i ++ {
bitmap [i ] = ^uint64 (0 )
}
bitmap [endword ] |= ^uint64 (0 ) >> (uint (-end ) % 64 )
}
bc .cardinality = invalidCardinality
return bc
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) lazyOR (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .lazyORArray (x )
case *bitmapContainer :
return bc .lazyORBitmap (x )
case *runContainer16 :
if x .isFull () {
return x .clone ()
}
return x .orBitmapContainer (bc )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) orArray (value2 *arrayContainer ) container {
answer := bc .clone ().(*bitmapContainer )
c := value2 .getCardinality ()
for k := 0 ; k < c ; k ++ {
v := value2 .content [k ]
i := uint (v ) >> 6
bef := answer .bitmap [i ]
aft := bef | (uint64 (1 ) << (v % 64 ))
answer .bitmap [i ] = aft
answer .cardinality += int ((bef - aft ) >> 63 )
}
return answer
}
func (bc *bitmapContainer ) orArrayCardinality (value2 *arrayContainer ) int {
answer := 0
c := value2 .getCardinality ()
for k := 0 ; k < c ; k ++ {
v := value2 .content [k ]
i := uint (v ) >> 6
bef := bc .bitmap [i ]
aft := bef | (uint64 (1 ) << (v % 64 ))
answer += int ((bef - aft ) >> 63 )
}
return answer
}
func (bc *bitmapContainer ) orBitmap (value2 *bitmapContainer ) container {
answer := newBitmapContainer ()
for k := 0 ; k < len (answer .bitmap ); k ++ {
answer .bitmap [k ] = bc .bitmap [k ] | value2 .bitmap [k ]
}
answer .computeCardinality ()
if answer .isFull () {
return newRunContainer16Range (0 , MaxUint16 )
}
return answer
}
func (bc *bitmapContainer ) orBitmapCardinality (value2 *bitmapContainer ) int {
return int (popcntOrSlice (bc .bitmap , value2 .bitmap ))
}
func (bc *bitmapContainer ) andBitmapCardinality (value2 *bitmapContainer ) int {
return int (popcntAndSlice (bc .bitmap , value2 .bitmap ))
}
func (bc *bitmapContainer ) computeCardinality () {
bc .cardinality = int (popcntSlice (bc .bitmap ))
}
func (bc *bitmapContainer ) iorArray (ac *arrayContainer ) container {
for k := range ac .content {
vc := ac .content [k ]
i := uint (vc ) >> 6
bef := bc .bitmap [i ]
aft := bef | (uint64 (1 ) << (vc % 64 ))
bc .bitmap [i ] = aft
bc .cardinality += int ((bef - aft ) >> 63 )
}
if bc .isFull () {
return newRunContainer16Range (0 , MaxUint16 )
}
return bc
}
func (bc *bitmapContainer ) iorBitmap (value2 *bitmapContainer ) container {
answer := bc
answer .cardinality = 0
for k := 0 ; k < len (answer .bitmap ); k ++ {
answer .bitmap [k ] = bc .bitmap [k ] | value2 .bitmap [k ]
}
answer .computeCardinality ()
if bc .isFull () {
return newRunContainer16Range (0 , MaxUint16 )
}
return answer
}
func (bc *bitmapContainer ) lazyIORArray (value2 *arrayContainer ) container {
answer := bc
c := value2 .getCardinality ()
for k := 0 ; k +3 < c ; k += 4 {
content := (*[4 ]uint16 )(unsafe .Pointer (&value2 .content [k ]))
vc0 := content [0 ]
i0 := uint (vc0 ) >> 6
answer .bitmap [i0 ] = answer .bitmap [i0 ] | (uint64 (1 ) << (vc0 % 64 ))
vc1 := content [1 ]
i1 := uint (vc1 ) >> 6
answer .bitmap [i1 ] = answer .bitmap [i1 ] | (uint64 (1 ) << (vc1 % 64 ))
vc2 := content [2 ]
i2 := uint (vc2 ) >> 6
answer .bitmap [i2 ] = answer .bitmap [i2 ] | (uint64 (1 ) << (vc2 % 64 ))
vc3 := content [3 ]
i3 := uint (vc3 ) >> 6
answer .bitmap [i3 ] = answer .bitmap [i3 ] | (uint64 (1 ) << (vc3 % 64 ))
}
for k := c &^ 3 ; k < c ; k ++ {
vc := value2 .content [k ]
i := uint (vc ) >> 6
answer .bitmap [i ] = answer .bitmap [i ] | (uint64 (1 ) << (vc % 64 ))
}
answer .cardinality = invalidCardinality
return answer
}
func (bc *bitmapContainer ) lazyORArray (value2 *arrayContainer ) container {
answer := bc .clone ().(*bitmapContainer )
return answer .lazyIORArray (value2 )
}
func (bc *bitmapContainer ) lazyIORBitmap (value2 *bitmapContainer ) container {
answer := bc
for k := 0 ; k < len (answer .bitmap ); k ++ {
answer .bitmap [k ] = bc .bitmap [k ] | value2 .bitmap [k ]
}
bc .cardinality = invalidCardinality
return answer
}
func (bc *bitmapContainer ) lazyORBitmap (value2 *bitmapContainer ) container {
answer := bc .clone ().(*bitmapContainer )
return answer .lazyIORBitmap (value2 )
}
func (bc *bitmapContainer ) xor (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .xorArray (x )
case *bitmapContainer :
return bc .xorBitmap (x )
case *runContainer16 :
return x .xorBitmap (bc )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) xorArray (value2 *arrayContainer ) container {
answer := bc .clone ().(*bitmapContainer )
c := value2 .getCardinality ()
for k := 0 ; k < c ; k ++ {
vc := value2 .content [k ]
index := uint (vc ) >> 6
abi := answer .bitmap [index ]
mask := uint64 (1 ) << (vc % 64 )
answer .cardinality += 1 - 2 *int ((abi &mask )>>(vc %64 ))
answer .bitmap [index ] = abi ^ mask
}
if answer .cardinality <= arrayDefaultMaxSize {
return answer .toArrayContainer ()
}
return answer
}
func (bc *bitmapContainer ) rank (x uint16 ) int {
leftover := (uint (x ) + 1 ) & 63
if leftover == 0 {
return int (popcntSlice (bc .bitmap [:(uint (x )+1 )/64 ]))
}
return int (popcntSlice (bc .bitmap [:(uint (x )+1 )/64 ]) + popcount (bc .bitmap [(uint (x )+1 )/64 ]<<(64 -leftover )))
}
func (bc *bitmapContainer ) selectInt (x uint16 ) int {
remaining := x
for k := 0 ; k < len (bc .bitmap ); k ++ {
w := popcount (bc .bitmap [k ])
if uint16 (w ) > remaining {
return k *64 + selectBitPosition (bc .bitmap [k ], int (remaining ))
}
remaining -= uint16 (w )
}
return -1
}
func (bc *bitmapContainer ) xorBitmap (value2 *bitmapContainer ) container {
newCardinality := int (popcntXorSlice (bc .bitmap , value2 .bitmap ))
if newCardinality > arrayDefaultMaxSize {
answer := newBitmapContainer ()
for k := 0 ; k < len (answer .bitmap ); k ++ {
answer .bitmap [k ] = bc .bitmap [k ] ^ value2 .bitmap [k ]
}
answer .cardinality = newCardinality
if answer .isFull () {
return newRunContainer16Range (0 , MaxUint16 )
}
return answer
}
ac := newArrayContainerSize (newCardinality )
fillArrayXOR (ac .content , bc .bitmap , value2 .bitmap )
ac .content = ac .content [:newCardinality ]
return ac
}
func (bc *bitmapContainer ) and (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .andArray (x )
case *bitmapContainer :
return bc .andBitmap (x )
case *runContainer16 :
if x .isFull () {
return bc .clone ()
}
return x .andBitmapContainer (bc )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) andCardinality (a container ) int {
switch x := a .(type ) {
case *arrayContainer :
return bc .andArrayCardinality (x )
case *bitmapContainer :
return bc .andBitmapCardinality (x )
case *runContainer16 :
return x .andBitmapContainerCardinality (bc )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) intersects (a container ) bool {
switch x := a .(type ) {
case *arrayContainer :
return bc .intersectsArray (x )
case *bitmapContainer :
return bc .intersectsBitmap (x )
case *runContainer16 :
return x .intersects (bc )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) iand (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .iandArray (x )
case *bitmapContainer :
return bc .iandBitmap (x )
case *runContainer16 :
if x .isFull () {
return bc .clone ()
}
return bc .iandRun16 (x )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) iandRun16 (rc *runContainer16 ) container {
rcb := newBitmapContainerFromRun (rc )
return bc .iandBitmap (rcb )
}
func (bc *bitmapContainer ) iandArray (ac *arrayContainer ) container {
acb := ac .toBitmapContainer ()
return bc .iandBitmap (acb )
}
func (bc *bitmapContainer ) andArray (value2 *arrayContainer ) *arrayContainer {
answer := newArrayContainerCapacity (len (value2 .content ))
answer .content = answer .content [:cap (answer .content )]
c := value2 .getCardinality ()
pos := 0
for k := 0 ; k < c ; k ++ {
v := value2 .content [k ]
answer .content [pos ] = v
pos += int (bc .bitValue (v ))
}
answer .content = answer .content [:pos ]
return answer
}
func (bc *bitmapContainer ) andArrayCardinality (value2 *arrayContainer ) int {
c := value2 .getCardinality ()
pos := 0
for k := 0 ; k < c ; k ++ {
v := value2 .content [k ]
pos += int (bc .bitValue (v ))
}
return pos
}
func (bc *bitmapContainer ) getCardinalityInRange (start , end uint ) int {
if start >= end {
return 0
}
firstword := start / 64
endword := (end - 1 ) / 64
const allones = ^uint64 (0 )
if firstword == endword {
return int (popcount (bc .bitmap [firstword ] & ((allones << (start % 64 )) & (allones >> ((64 - end ) & 63 )))))
}
answer := popcount (bc .bitmap [firstword ] & (allones << (start % 64 )))
answer += popcntSlice (bc .bitmap [firstword +1 : endword ])
answer += popcount (bc .bitmap [endword ] & (allones >> ((64 - end ) & 63 )))
return int (answer )
}
func (bc *bitmapContainer ) andBitmap (value2 *bitmapContainer ) container {
newcardinality := int (popcntAndSlice (bc .bitmap , value2 .bitmap ))
if newcardinality > arrayDefaultMaxSize {
answer := newBitmapContainer ()
for k := 0 ; k < len (answer .bitmap ); k ++ {
answer .bitmap [k ] = bc .bitmap [k ] & value2 .bitmap [k ]
}
answer .cardinality = newcardinality
return answer
}
ac := newArrayContainerSize (newcardinality )
fillArrayAND (ac .content , bc .bitmap , value2 .bitmap )
ac .content = ac .content [:newcardinality ]
return ac
}
func (bc *bitmapContainer ) intersectsArray (value2 *arrayContainer ) bool {
c := value2 .getCardinality ()
for k := 0 ; k < c ; k ++ {
v := value2 .content [k ]
if bc .contains (v ) {
return true
}
}
return false
}
func (bc *bitmapContainer ) intersectsBitmap (value2 *bitmapContainer ) bool {
for k := 0 ; k < len (bc .bitmap ); k ++ {
if (bc .bitmap [k ] & value2 .bitmap [k ]) != 0 {
return true
}
}
return false
}
func (bc *bitmapContainer ) iandBitmap (value2 *bitmapContainer ) container {
newcardinality := int (popcntAndSlice (bc .bitmap , value2 .bitmap ))
for k := 0 ; k < len (bc .bitmap ); k ++ {
bc .bitmap [k ] = bc .bitmap [k ] & value2 .bitmap [k ]
}
bc .cardinality = newcardinality
if newcardinality <= arrayDefaultMaxSize {
return newArrayContainerFromBitmap (bc )
}
return bc
}
func (bc *bitmapContainer ) andNot (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .andNotArray (x )
case *bitmapContainer :
return bc .andNotBitmap (x )
case *runContainer16 :
return bc .andNotRun16 (x )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) andNotRun16 (rc *runContainer16 ) container {
rcb := rc .toBitmapContainer ()
return bc .andNotBitmap (rcb )
}
func (bc *bitmapContainer ) iandNot (a container ) container {
switch x := a .(type ) {
case *arrayContainer :
return bc .iandNotArray (x )
case *bitmapContainer :
return bc .iandNotBitmapSurely (x )
case *runContainer16 :
return bc .iandNotRun16 (x )
}
panic ("unsupported container type" )
}
func (bc *bitmapContainer ) iandNotArray (ac *arrayContainer ) container {
if ac .isEmpty () || bc .isEmpty () {
return bc
}
wordIdx := uint16 (0 )
mask := uint64 (0 )
for i , v := range ac .content {
if v /64 != wordIdx {
if i != 0 {
mask &= bc .bitmap [wordIdx ]
bc .bitmap [wordIdx ] &= ^mask
bc .cardinality -= int (popcount (mask ))
}
wordIdx = v / 64
mask = 0
}
mask |= 1 << (v % 64 )
}
mask &= bc .bitmap [wordIdx ]
bc .bitmap [wordIdx ] &= ^mask
bc .cardinality -= int (popcount (mask ))
if bc .getCardinality () <= arrayDefaultMaxSize {
return bc .toArrayContainer ()
}
return bc
}
func (bc *bitmapContainer ) iandNotRun16 (rc *runContainer16 ) container {
if rc .isEmpty () || bc .isEmpty () {
return bc
}
wordRangeStart := rc .iv [0 ].start / 64
wordRangeEnd := (rc .iv [len (rc .iv )-1 ].last ()) / 64
cardinalityChange := popcntSlice (bc .bitmap [wordRangeStart : wordRangeEnd +1 ])
for _ , iv := range rc .iv {
resetBitmapRange (bc .bitmap , int (iv .start ), int (iv .last ())+1 )
}
cardinalityChange -= popcntSlice (bc .bitmap [wordRangeStart : wordRangeEnd +1 ])
bc .cardinality -= int (cardinalityChange )
if bc .getCardinality () <= arrayDefaultMaxSize {
return bc .toArrayContainer ()
}
return bc
}
func (bc *bitmapContainer ) andNotArray (value2 *arrayContainer ) container {
answer := bc .clone ().(*bitmapContainer )
c := value2 .getCardinality ()
for k := 0 ; k < c ; k ++ {
vc := value2 .content [k ]
i := uint (vc ) >> 6
oldv := answer .bitmap [i ]
newv := oldv &^ (uint64 (1 ) << (vc % 64 ))
answer .bitmap [i ] = newv
answer .cardinality -= int ((oldv ^ newv ) >> (vc % 64 ))
}
if answer .cardinality <= arrayDefaultMaxSize {
return answer .toArrayContainer ()
}
return answer
}
func (bc *bitmapContainer ) andNotBitmap (value2 *bitmapContainer ) container {
newCardinality := int (popcntMaskSlice (bc .bitmap , value2 .bitmap ))
if newCardinality > arrayDefaultMaxSize {
answer := newBitmapContainer ()
for k := 0 ; k < len (answer .bitmap ); k ++ {
answer .bitmap [k ] = bc .bitmap [k ] &^ value2 .bitmap [k ]
}
answer .cardinality = newCardinality
return answer
}
ac := newArrayContainerSize (newCardinality )
fillArrayANDNOT (ac .content , bc .bitmap , value2 .bitmap )
return ac
}
func (bc *bitmapContainer ) iandNotBitmapSurely (value2 *bitmapContainer ) container {
newCardinality := int (popcntMaskSlice (bc .bitmap , value2 .bitmap ))
for k := 0 ; k < len (bc .bitmap ); k ++ {
bc .bitmap [k ] = bc .bitmap [k ] &^ value2 .bitmap [k ]
}
bc .cardinality = newCardinality
if bc .getCardinality () <= arrayDefaultMaxSize {
return bc .toArrayContainer ()
}
return bc
}
func (bc *bitmapContainer ) contains (i uint16 ) bool {
x := uint (i )
w := bc .bitmap [x >>6 ]
mask := uint64 (1 ) << (x & 63 )
return (w & mask ) != 0
}
func (bc *bitmapContainer ) bitValue (i uint16 ) uint64 {
x := uint (i )
w := bc .bitmap [x >>6 ]
return (w >> (x & 63 )) & 1
}
func (bc *bitmapContainer ) loadData (arrayContainer *arrayContainer ) {
bc .cardinality = arrayContainer .getCardinality ()
c := arrayContainer .getCardinality ()
for k := 0 ; k < c ; k ++ {
x := arrayContainer .content [k ]
i := int (x ) / 64
bc .bitmap [i ] |= (uint64 (1 ) << uint (x %64 ))
}
}
func (bc *bitmapContainer ) resetTo (a container ) {
switch x := a .(type ) {
case *arrayContainer :
fill (bc .bitmap , 0 )
bc .loadData (x )
case *bitmapContainer :
bc .cardinality = x .cardinality
copy (bc .bitmap , x .bitmap )
case *runContainer16 :
bc .cardinality = len (x .iv )
lastEnd := 0
for _ , r := range x .iv {
bc .cardinality += int (r .length )
resetBitmapRange (bc .bitmap , lastEnd , int (r .start ))
lastEnd = int (r .start +r .length ) + 1
setBitmapRange (bc .bitmap , int (r .start ), lastEnd )
}
resetBitmapRange (bc .bitmap , lastEnd , maxCapacity )
default :
panic ("unsupported container type" )
}
}
func (bc *bitmapContainer ) toArrayContainer () *arrayContainer {
ac := &arrayContainer {}
ac .loadData (bc )
return ac
}
func (bc *bitmapContainer ) fillArray (container []uint16 ) {
pos := 0
base := 0
for k := 0 ; k < len (bc .bitmap ); k ++ {
bitset := bc .bitmap [k ]
for bitset != 0 {
t := bitset & -bitset
container [pos ] = uint16 ((base + int (popcount (t -1 ))))
pos = pos + 1
bitset ^= t
}
base += 64
}
}
func (bc *bitmapContainer ) NextSetBit (i uint ) int {
var (
x = i / 64
length = uint (len (bc .bitmap ))
)
if x >= length {
return -1
}
w := bc .bitmap [x ]
w = w >> uint (i %64 )
if w != 0 {
return int (i ) + countTrailingZeros (w )
}
x ++
for ; x < length ; x ++ {
if bc .bitmap [x ] != 0 {
return int (x *64 ) + countTrailingZeros (bc .bitmap [x ])
}
}
return -1
}
func (bc *bitmapContainer ) PrevSetBit (i int ) int {
if i < 0 {
return -1
}
x := i / 64
if x >= len (bc .bitmap ) {
return -1
}
w := bc .bitmap [x ]
b := i % 64
w = w << uint (63 -b )
if w != 0 {
return i - countLeadingZeros (w )
}
x --
for ; x >= 0 ; x -- {
if bc .bitmap [x ] != 0 {
return (x * 64 ) + 63 - countLeadingZeros (bc .bitmap [x ])
}
}
return -1
}
func (bc *bitmapContainer ) numberOfRuns () int {
if bc .cardinality == 0 {
return 0
}
var numRuns uint64
nextWord := bc .bitmap [0 ]
for i := 0 ; i < len (bc .bitmap )-1 ; i ++ {
word := nextWord
nextWord = bc .bitmap [i +1 ]
numRuns += popcount ((^word )&(word <<1 )) + ((word >> 63 ) &^ nextWord )
}
word := nextWord
numRuns += popcount ((^word ) & (word << 1 ))
if (word & 0x8000000000000000 ) != 0 {
numRuns ++
}
return int (numRuns )
}
func (bc *bitmapContainer ) toEfficientContainer () container {
numRuns := bc .numberOfRuns ()
sizeAsRunContainer := runContainer16SerializedSizeInBytes (numRuns )
sizeAsBitmapContainer := bitmapContainerSizeInBytes ()
card := bc .getCardinality ()
sizeAsArrayContainer := arrayContainerSizeInBytes (card )
if sizeAsRunContainer <= minOfInt (sizeAsBitmapContainer , sizeAsArrayContainer ) {
return newRunContainer16FromBitmapContainer (bc )
}
if card <= arrayDefaultMaxSize {
return bc .toArrayContainer ()
}
return bc
}
func newBitmapContainerFromRun(rc *runContainer16 ) *bitmapContainer {
if len (rc .iv ) == 1 {
return newBitmapContainerwithRange (int (rc .iv [0 ].start ), int (rc .iv [0 ].last ()))
}
bc := newBitmapContainer ()
for i := range rc .iv {
setBitmapRange (bc .bitmap , int (rc .iv [i ].start ), int (rc .iv [i ].last ())+1 )
bc .cardinality += int (rc .iv [i ].last ()) + 1 - int (rc .iv [i ].start )
}
return bc
}
func (bc *bitmapContainer ) containerType () contype {
return bitmapContype
}
func (bc *bitmapContainer ) addOffset (x uint16 ) (container , container ) {
var low , high *bitmapContainer
if bc .cardinality == 0 {
return nil , nil
}
b := uint32 (x ) >> 6
i := uint32 (x ) % 64
end := uint32 (1024 ) - b
low = newBitmapContainer ()
if i == 0 {
copy (low .bitmap [b :], bc .bitmap [:end ])
} else {
low .bitmap [b ] = bc .bitmap [0 ] << i
for k := uint32 (1 ); k < end ; k ++ {
newval := bc .bitmap [k ] << i
newval |= bc .bitmap [k -1 ] >> (64 - i )
low .bitmap [b +k ] = newval
}
}
low .computeCardinality ()
if low .cardinality == bc .cardinality {
return low , nil
}
if low .cardinality == 0 {
high = low
low = nil
} else {
high = newBitmapContainer ()
}
if i == 0 {
copy (high .bitmap [:b ], bc .bitmap [end :])
} else {
for k := end ; k < 1024 ; k ++ {
newval := bc .bitmap [k ] << i
newval |= bc .bitmap [k -1 ] >> (64 - i )
high .bitmap [k -end ] = newval
}
high .bitmap [b ] = bc .bitmap [1023 ] >> (64 - i )
}
high .computeCardinality ()
if low == nil {
return nil , high
}
return low , high
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .